﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DirectorySlicer
{
    /// <summary>
    /// class to load files from a path as a thread. 
    /// </summary>
    class FileCollector
    {
        private List<FileContainer> filesFound = new List<FileContainer>();
        private String folderPath;

        public FileCollector(String folderPath)
        {
            this.folderPath = folderPath;
        }

        public List<FileContainer> getFileList()
        {
            return filesFound;
        }

        /// <summary>
        /// method to start as threadstart for collecting the files
        /// </summary>
        /// <param name="form"> form where the log will be invoked</param>
        public void loadFileList(Form1 form)
        {
            Stack<string> dirs = new Stack<string>(20);
            if (!System.IO.Directory.Exists(folderPath))
            {
                form.Invoke(new Logger.UpdateLogCallback(Logger.Log), "ERROR: Path not found (" + folderPath + ")");
                return;
            }
            dirs.Push(folderPath);
            long sizeInByte = 0;
            while (dirs.Count > 0)
            {
                string currentDir = dirs.Pop();
                string[] subDirs;
                try
                {
                    subDirs = System.IO.Directory.GetDirectories(currentDir);
                }
                // An UnauthorizedAccessException exception will be thrown if we do not have
                // discovery permission on a folder or file. It may or may not be acceptable 
                // to ignore the exception and continue enumerating the remaining files and 
                // folders. It is also possible (but unlikely) that a DirectoryNotFound exception 
                // will be raised. This will happen if currentDir has been deleted by
                // another application or thread after our call to Directory.Exists. The 
                // choice of which exceptions to catch depends entirely on the specific task 
                // you are intending to perform and also on how much you know with certainty 
                // about the systems on which this code will run.
                catch (UnauthorizedAccessException)
                {
                    form.Invoke(new Logger.UpdateLogCallback(Logger.Log), "WARNING: Access to subfolders denied in directory " + currentDir);
                    continue;
                }
                catch (System.IO.DirectoryNotFoundException)
                {
                    form.Invoke(new Logger.UpdateLogCallback(Logger.Log), "WARNING: Path not found (" + currentDir + ")");
                    continue;
                }

                string[] files = null;
                try
                {
                    files = System.IO.Directory.GetFiles(currentDir);
                }
                catch (UnauthorizedAccessException)
                {
                    form.Invoke(new Logger.UpdateLogCallback(Logger.Log), "WARNING: Access to files denied in directory " + currentDir);
                    continue;
                }
                catch (System.IO.DirectoryNotFoundException)
                {
                    form.Invoke(new Logger.UpdateLogCallback(Logger.Log), "WARNING: Path not found (" + currentDir + ")");
                    continue;
                }
                // Perform the required action on each file here.
                // Modify this block to perform your required task.
                foreach (string file in files)
                {
                    FileContainer container = new FileContainer(file);
                    if (container.getSize() >= 0){
                        filesFound.Add(container);
                        sizeInByte+=container.getSize();
                    }
                    else
                        form.Invoke(new Logger.UpdateLogCallback(Logger.Log), "WARNING: some files cannot be loaded from " + currentDir + "");
                }

                // Push the subdirectories onto the stack for traversal.
                // This could also be done before handing the files.
                foreach (string str in subDirs)
                    dirs.Push(str);
            }
            form.Invoke(new Logger.UpdateLogCallback(Logger.Log),this.filesFound.Count + " files (~" + (((int)(sizeInByte/(1000.0*10)))/100.0) + " MB) found in " + folderPath);
        }
    }
}
